#!/usr/local/bin/ruby
require 'twitterbot'

REVIEWERS_TO_ASK = 3
SUPPORTERS_NEEDED = 1

Moments = {}
class Moment < Project
   attr_accessor :what, :author, :supported_by, :rejected_by, :last_announced

   def initialize(what, author)
      super
      @what = what
      @author = author
      @supported_by = []; @rejected_by = []
      Moments[what] = self
   end
   
   def msg; "global moment of #{what}, in 1 minute!"; end
   def upcoming_message
      "global moment of #{what} at #{announce_time}"
   end
   
   def rejected?; rejected_by.size > 0; end   
   def accepted?; supported_by.size > SUPPORTERS_NEEDED; end
   
   # action items
   def start_review(p)
      return true if moment.accepted?
      # p.tell "Your moment is under review!"
      f = bot.available_friends.select{|f| f.usable? }.sort_by{|f| f.last_used || 0 }.first
      f.tell(
         "someone requested a global moment of #{text}.  should we do it?",
         [self, :review_answered]
      )
      return true
   end

   def inform_if_accepted_or_rejected(p)
      return false unless accepted? or rejected?
      if rejected?
         p.tell "Your suggested of a global moment of #{what} has been rejected."
      elsif p.bot.next_moment and p.bot.next_moment == self
         p.tell "your moment has been scheduled.  #{upcoming_message}"
      end
   end

   def announce(bot)
      return true if rejected?
      return false if not accepted?
      bot.next_moment = self unless bot.next_moment
      return false if bot.next_moment != self
      return false unless 60.minutes.elapsed_since?(bot.last_moment.last_announced)
      bot.twitter msg
      bot.last_moment, bot.next_moment = self, nil
      last_announced = Time.now
   end

   # waiting fors
   def review_answered(p, answer)
      if answer =~ /yes/
         moment.supported_by << p
      else
         moment.rejected_by << p
      end
      return true
   end
end

# Jabber::debug = true

class WorldMomentsBot < TwitterBot
   attr_accessor :next_moment, :last_moment
   
   def initialize(*args)
      super(*args)
      @last_moment = @next_moment = nil
      jabber.accept_subscriptions = true
      every (30.minutes) { befriend_all_followers }
      every (5.seconds)  { scan_friends; scan_messages; @next_moment.process_obligations if @next_moment }
      #every (5.seconds)  { scan_messages; @next_moment.next_action! if @next_moment }
   end
   
   ### basics ###
   def greeting(type, sender, text)
      return false if type == :twitter and not text.sub! /global moment of /
      return status_report(sender) if type == :im
      submission(sender, text)
   end

   def status_report(to)
      to.tell(
         if    @next_moment then @next_moment.upcoming_message
         elsif @last_moment then "nothing scheduled since #{@last_moment.upcoming_message}"
         else "nothing yet"
         end
      )
   end

   ### submissions ###
   def submission(p, text)
      %w{global moment of}.each { |word| text.sub!(/^#{word} /, ''); text.strip! }
      return unless check_submission(p, text)
      moment ||= Moment.new(text, p)
      moment << [:start_review, p] << [:inform_if_accepted_or_rejected, p] << [:announce, self]
      moment.next_action!
   end
   
   def check_submission(p, text)
      return false if text.size < 3      
      if moment = Moments[text] and moment.rejected?
         p.tell "that moment has been proposed before and rejected.  sorry."
         return false
      end
      if next_moment
         p.tell "there's already a moment scheduled, please resubmit later. #{next_moment.upcoming_message}"
         return false
      end
      if (not moment or not moment.accepted?) and available_friends.empty?
         p.tell "I'm sorry, not enough people are online to review that moment.  Try again later."
         return false
      end
      return true
   end
end   



WorldMomentsBot.new('worldmoments@gmail.com', 'popple').daemonize
